home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Games / SinkShips 2.2.2 / SinkShips.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  32.0 KB  |  1,602 lines  |  [TEXT/CWIE]

  1. /* ----------------------------------------------------------------------
  2.  
  3.     SinkShips
  4.     version 2.2.2
  5.     
  6.     Written by: Matthew Kavalauskas
  7.     Ported to CW by: Paul Celestin
  8.         
  9.     951215 - 2.2.1 - original CW release
  10.     960704 - 2.2.2 - updated for CW9
  11.  
  12. ---------------------------------------------------------------------- */
  13.  
  14. #include    "SinkShips.h"
  15.  
  16. /********/
  17. /* main */
  18. /********/
  19.  
  20. void    main ( void )
  21. {
  22.     ToolBoxInit ();
  23.     MenuBarInit ();
  24.     
  25.     HandleAppleChoice ( iAbout );
  26.     useColor = IsColour();
  27.  
  28.     WindowInit ();
  29.     PlaceEnemyShips ();
  30.     
  31.     NewGame ();
  32.     EventLoop ();
  33. }
  34.             
  35.  
  36. /**************/
  37. /* ToolBoxInit*/
  38. /**************/
  39.  
  40. void    ToolBoxInit ( void )
  41. {
  42.     InitGraf ( &qd.thePort );
  43.     InitFonts ();
  44.     InitWindows ();
  45.     InitMenus ();
  46.     TEInit ();
  47.     InitDialogs ( nil );
  48.     InitCursor ();
  49. }
  50.  
  51. /**************/
  52. /* WindowInit */
  53. /**************/
  54.  
  55. void    WindowInit ( void )
  56. {
  57.     if ( useColor )
  58.         youWindow = GetNewCWindow ( kYouWindowID, nil, kMoveToFront );
  59.     else
  60.         youWindow = GetNewWindow ( kYouWindowID, nil, kMoveToFront );
  61.     
  62.     if ( youWindow == nil )
  63.     {
  64.         SysBeep ( 10 );
  65.         ExitToShell ();
  66.     }
  67.     
  68.     SetWRefCon ( youWindow, (long) kYouWindowID );
  69.  
  70.     SetPort ( youWindow );
  71.     ShowWindow ( youWindow );
  72.  
  73.     if ( useColor )
  74.         enemyWindow = GetNewCWindow ( kEnemyWindowID, nil, kMoveToFront );
  75.     else
  76.         enemyWindow = GetNewWindow ( kEnemyWindowID, nil, kMoveToFront );
  77.     
  78.     if ( enemyWindow == nil )
  79.     {
  80.         SysBeep ( 10 );
  81.         ExitToShell ();
  82.     }
  83.     
  84.     SetWRefCon ( enemyWindow, (long) kEnemyWindowID );
  85.     SetPort ( enemyWindow );
  86.     ShowWindow ( enemyWindow );
  87. }
  88.  
  89.  
  90. /***************/
  91. /* MenuBarInit */
  92. /***************/
  93.  
  94. void    MenuBarInit ( void )
  95. {
  96.     Handle            menuBar;
  97.     MenuHandle        menu;
  98.     
  99.     menuBar = GetNewMBar ( kBaseResID );
  100.     SetMenuBar ( menuBar );
  101.     
  102.     menu = GetMHandle ( mApple );
  103.     AddResMenu ( menu, 'DRVR' );
  104.     
  105.     DrawMenuBar ();
  106.     
  107.     HandleSound ();
  108. }
  109.  
  110. /***************/
  111. /* HandleSound */
  112. /***************/
  113.  
  114. void    HandleSound ( void )
  115. {
  116.     MenuHandle    menuHandle;
  117.     
  118.     menuHandle = GetMHandle ( mOptions );
  119.     
  120.     
  121.     if ( gHasSound )
  122.     {
  123.         CheckItem ( menuHandle, iSound, kRemoveCheckMark );
  124.         gHasSound = !gHasSound;
  125.     }
  126.     else
  127.     {
  128.         CheckItem ( menuHandle, iSound, kAddCheckMark );
  129.         gHasSound = !gHasSound;
  130.     }
  131. }
  132.  
  133. /*************/
  134. /* EventLoop */
  135. /*************/
  136.  
  137. void    EventLoop ( void )
  138. {
  139.     EventRecord    event;
  140.     DialogPtr    dialog;
  141.     Boolean        dialogDone = FALSE;
  142.     short            result;
  143.     Handle        mySndHandle;
  144.     
  145.     gDone = false;
  146.     while ( gDone == false )
  147.     {
  148.         if ( WaitNextEvent ( everyEvent, &event, MAXLONG, nil ) )
  149.             DoEvent ( &event );
  150.  
  151.         if ( enemyCount >= 17 ) /* you win! */
  152.         {
  153.             SelectWindow ( enemyWindow );
  154.             SetPort ( enemyWindow );
  155.             DrawDots ( enemy );
  156.             
  157.             if ( gHasSound )
  158.             {
  159.                 mySndHandle = GetResource ( 'snd ', kYouWinSnd );
  160.                 if ( mySndHandle != NULL )
  161.                     SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  162.             }
  163.             
  164.             dialog = GetNewDialog ( kBaseResID + 1, nil, kMoveToFront );
  165.             SetDialogDefaultItem ( dialog, ok );
  166.             SetDialogCancelItem ( dialog, cancel );
  167.             ParamText( kCongratulationsStr, kYouWinStr, "\p", "\p" );
  168.             SetPort ( dialog );
  169.             ShowWindow ( dialog );
  170.             while ( !dialogDone )
  171.             {
  172.                 ModalDialog ( nil, &result );
  173.                 
  174.                 switch ( result )
  175.                 {
  176.                     case ok:
  177.                         dialogDone = TRUE;
  178.                         DisposDialog  ( dialog );
  179.                         NewGame ();
  180.                         break;
  181.                     case cancel:
  182.                         DisposDialog  ( dialog );
  183.                         dialogDone = TRUE;
  184.                         gDone = TRUE;
  185.                         break;
  186.                 }
  187.             }
  188.             dialogDone = FALSE;
  189.         }
  190.         else if ( ( gYouHasGone ) && ( !gDone ) )
  191.         {
  192.             PickEnemyShot ();
  193.             gYouHasGone = !gYouHasGone;
  194.         }
  195.         if ( youCount >= 17 ) /* computer wins! */
  196.         {
  197.             SelectWindow ( enemyWindow );
  198.             SetPort ( enemyWindow );
  199.             DrawDots ( enemy );
  200.             
  201.             if ( gHasSound )
  202.             {
  203.                 mySndHandle = GetResource ( 'snd ', kYouLoseSnd );
  204.                 if ( mySndHandle != NULL )
  205.                     SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  206.             }
  207.             
  208.             dialog = GetNewDialog ( kBaseResID + 1, nil, kMoveToFront );
  209.             SetDialogDefaultItem ( dialog, ok );
  210.             SetDialogCancelItem ( dialog, cancel );
  211.             ParamText( kSorryStr, kYouLoseStr, "\p", "\p" );
  212.             SetPort ( dialog );
  213.             ShowWindow ( dialog );
  214.             while ( !dialogDone )
  215.             {
  216.                 ModalDialog ( nil, &result );
  217.                 
  218.                 switch ( result )
  219.                 {
  220.                     case ok:
  221.                         dialogDone = TRUE;
  222.                         DisposDialog  ( dialog );
  223.                         NewGame ();
  224.                         break;
  225.                     case cancel:
  226.                         DisposDialog  ( dialog );
  227.                         dialogDone = TRUE;
  228.                         gDone = TRUE;
  229.                         break;
  230.                 }
  231.             }
  232.             dialogDone = FALSE;
  233.         }
  234.     }
  235. }
  236.  
  237.  
  238. /***********/
  239. /* DoEvent */
  240. /***********/
  241.  
  242. void    DoEvent ( EventRecord *eventPtr )
  243. {
  244.     Boolean    becomingActive;
  245.     char    theChar;
  246.     
  247.     switch ( eventPtr->what )
  248.     {
  249.         case mouseDown:
  250.             HandleMouseDown ( eventPtr );
  251.             break;
  252.         case keyDown:
  253.         case autoKey:
  254.             theChar = eventPtr->message & charCodeMask;
  255.             if ( (eventPtr->modifiers & cmdKey) != 0 )
  256.                 HandleMenuChoice ( MenuKey ( theChar ) );
  257.             break;
  258.         case updateEvt:
  259.             DoUpdate ( eventPtr );
  260.             break;
  261.         case activateEvt:
  262.             becomingActive = ( ( eventPtr->modifiers &activeFlag ) == activeFlag );
  263.             break;
  264.     }
  265. }
  266.  
  267. /*******************/
  268. /* HandleMouseDown */
  269. /*******************/
  270.  
  271. void    HandleMouseDown ( EventRecord *eventPtr )
  272. {
  273.     WindowPtr    window;
  274.     short int    thePart;
  275.     long        menuChoice;
  276.     
  277.     thePart = FindWindow ( eventPtr->where, &window );
  278.     
  279.     switch ( thePart )
  280.     {
  281.         case inMenuBar:
  282.             menuChoice = MenuSelect ( eventPtr->where );
  283.             HandleMenuChoice ( menuChoice );
  284.             break;
  285.         case inSysWindow:
  286.             SystemClick ( eventPtr, window );
  287.             break;
  288.         case inContent:
  289.             SelectWindow ( window );
  290.             if ( GetWRefCon ( window ) == kEnemyWindowID )
  291.             {
  292.                 SetPort ( window );
  293.                 CheckPoint ( eventPtr->where );
  294.             }
  295.             break;
  296.         case inDrag:
  297.             DragWindow ( window, eventPtr->where, &qd.screenBits.bounds );
  298.             break;
  299.         case inGoAway:
  300.             if ( TrackGoAway ( window, eventPtr->where ) )
  301.                 gDone = true;
  302.             break;
  303.     }
  304. }
  305.  
  306. /************/
  307. /* DoUpdate */
  308. /************/
  309.  
  310. void    DoUpdate ( EventRecord *eventPtr )
  311. {
  312.     WindowPtr    window;
  313.     
  314.     window = ( WindowPtr ) eventPtr->message;
  315.     
  316.     BeginUpdate ( window );
  317.     
  318.     if ( GetWRefCon ( window ) == kEnemyWindowID )
  319.     {
  320.         SetPort ( window );
  321.         DrawDots ( enemy );
  322.     }
  323.  
  324.     if ( GetWRefCon ( window ) == kYouWindowID )
  325.     {
  326.         SetPort ( window );
  327.         DrawDots ( you );
  328.     }
  329.     
  330.     EndUpdate ( window );
  331. }
  332.  
  333. /********************/
  334. /* HandleMenuChoice */
  335. /********************/
  336.  
  337. void    HandleMenuChoice ( long menuChoice )
  338. {
  339.     short    menu;
  340.     short    item;
  341.     
  342.     if ( menuChoice != 0 )
  343.     {
  344.         menu = HiWord ( menuChoice );
  345.         item = LoWord ( menuChoice );
  346.         
  347.         switch ( menu )
  348.         {
  349.             case mApple:
  350.                 HandleAppleChoice ( item );
  351.                 break;
  352.             case mFile:
  353.                 HandleFileChoice ( item );
  354.                 break;
  355.             case mOptions:
  356.                 HandleOptionsChoice ( item );
  357.         }
  358.         
  359.         HiliteMenu ( 0 );
  360.     }
  361. }
  362.  
  363. /********************/
  364. /* HandleAppleChoice*/
  365. /********************/
  366.  
  367. void    HandleAppleChoice ( short item )
  368. {
  369.     MenuHandle    appleMenu;
  370.     Handle        mySndHandle;
  371.     Str255        accName;
  372.     short        accNumber;
  373.     DialogPtr    dialog;
  374.     Boolean        dialogDone = FALSE, showHelp = FALSE;
  375.     short        result;
  376.     
  377.     if ( gHasSound )
  378.     {
  379.         mySndHandle = GetResource ( 'snd ', kBombDropSnd );
  380.         if ( mySndHandle != NULL )
  381.             SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  382.         
  383.         mySndHandle = GetResource ( 'snd ', kExplosionSnd );
  384.         if ( mySndHandle != NULL )
  385.             SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  386.     }
  387.     
  388.     switch ( item )
  389.     {
  390.         case iAbout:
  391.             dialog = GetNewDialog ( kBaseResID + 3, nil, kMoveToFront );
  392.             ParamText( kVersionNumberStr, "\p", "\p", "\p" );
  393.             SetDialogDefaultItem ( dialog, ok );
  394.             SetDialogCancelItem ( dialog, cancel );
  395.             SetPort ( dialog );
  396.             ShowWindow ( dialog );
  397.             
  398.             while ( !dialogDone )
  399.             {
  400.                 ModalDialog ( nil, &result );
  401.                 
  402.                 switch ( result )
  403.                 {
  404.                     case ok:
  405.                         dialogDone = TRUE;
  406.                         break;
  407.                     case cancel:
  408.                         showHelp = TRUE;
  409.                         dialogDone = TRUE;
  410.                         break;
  411.                 }
  412.             }
  413.             DisposDialog  ( dialog );
  414.             dialogDone = FALSE;
  415.         
  416.             if ( showHelp )
  417.             {
  418.                 dialog = GetNewDialog ( kBaseResID + 4, nil, kMoveToFront );
  419.                 ParamText( kVersionNumberStr, "\p", "\p", "\p" );
  420.                 SetDialogDefaultItem ( dialog, ok );
  421.                 SetPort ( dialog );
  422.                 ShowWindow ( dialog );
  423.                 while ( !dialogDone )
  424.                 {
  425.                     ModalDialog ( nil, &result );
  426.                     
  427.                     switch ( result )
  428.                     {
  429.                         case ok:
  430.                             dialogDone = TRUE;
  431.                             break;
  432.                     }
  433.                 }
  434.                 DisposDialog  ( dialog );
  435.             }
  436.             break;
  437.         default:
  438.             appleMenu = GetMHandle ( mApple );
  439.             GetItem ( appleMenu, item, accName );
  440.             accNumber = OpenDeskAcc ( accName );
  441.             break;
  442.     }
  443. }
  444.  
  445. /********************/
  446. /* HandleFileChoice */
  447. /********************/
  448.  
  449. void     HandleFileChoice ( short item )
  450. {
  451.     switch ( item )
  452.     {
  453.         case iQuit:
  454.             gDone = TRUE;
  455.             break;
  456.         case iNew:
  457.             NewGame ();
  458.             break;
  459.     }
  460. }
  461.  
  462. /***********************/
  463. /* HandleOptionsChoice */
  464. /***********************/
  465.  
  466. void    HandleOptionsChoice ( short item )
  467. {
  468.     switch ( item )
  469.     {
  470.         case iSound:
  471.             HandleSound ();
  472.             break;
  473.     }
  474. }
  475.  
  476. /***********/
  477. /* NewGame */
  478. /***********/
  479.  
  480. void    NewGame ( void )
  481. {
  482.     int            i;
  483.     DialogPtr    dialog;
  484.     
  485.     youCount = 0;
  486.     enemyCount = 0;
  487.     shotCount = 0;
  488.     gYouHasGone = FALSE;
  489.     
  490.     for ( i = 0; i < kNumShips; i++ )
  491.         hitShips[i] = 0;
  492.     
  493.     GridInit ( enemy );
  494.     GridInit ( you );
  495.     SetPort ( enemyWindow );
  496.     DrawDots ( enemy );
  497.     SetPort ( youWindow );
  498.     DrawDots ( you );
  499.     PlaceEnemyShips ();
  500.     
  501.     dialog = GetNewDialog ( kBaseResID, nil, kMoveToFront );
  502.     SetDialogDefaultItem ( dialog, ok );
  503.     SetDialogCancelItem ( dialog, cancel );
  504.     ParamText( kRotateStr, kPlaceStr, "\p", "\p" );
  505.     SetPort ( dialog );
  506.     ShowWindow ( dialog );
  507.     DrawDialog ( dialog );
  508.     
  509.     SelectWindow ( youWindow );
  510.     SetPort ( youWindow );
  511.     
  512.     PlaceAShip ( kCarrierMin, kCarrierMax, kHorizCarrierID, kCarrier );
  513.     PlaceAShip ( kSinkShipMin, kSinkShipMax, kHorizSinkShipID, kSinkShip );
  514.     PlaceAShip ( kCruiserMin, kCruiserMax, kHorizCruiserID, kCruiser );
  515.     PlaceAShip ( kSubMin, kSubMax, kHorizSubID, kSub );
  516.     PlaceAShip ( kDestroyerMin, kDestroyerMax, kHorizDestroyerID, kDestroyer );
  517.     
  518.     DisposeDialog ( dialog );
  519.     
  520.     SelectWindow ( enemyWindow );
  521.     SetPort ( enemyWindow );
  522. }
  523.  
  524. /**************/
  525. /* PlaceAShip */
  526. /**************/
  527.  
  528. void    PlaceAShip ( int theMin, int theMax, int theHorizID, int theShip )
  529. {
  530.     EventRecord            event;
  531.     Point                thePoint, tempPoint, oldPoint;
  532.     Rect                theRect, tempRect, oldRect;
  533.     char                theChar;
  534.     Boolean                horiz = TRUE, oldHoriz = TRUE;
  535.     
  536.     do /* gets a random temp point for the placement of the first ship */
  537.     {
  538.         tempPoint.v = Randomize ();
  539.         tempPoint.h = Randomize ();
  540.         
  541.         Inbounds ( &tempPoint, horiz, theMin, theMax );
  542.  
  543.     } while ( !ItFits ( horiz, tempPoint, theMin, theMax ) );
  544.     
  545.     PtToShipRect ( tempPoint, &oldRect, horiz, theMin, theMax );
  546.     PtToRect ( tempPoint, &tempRect );
  547.     oldPoint = tempPoint;
  548.     
  549.     DrawShipPart ( theHorizID, oldRect );
  550.     
  551.     while ( !Button () )
  552.     {
  553.         GetMouse ( &thePoint );
  554.  
  555.         if ( WaitNextEvent ( everyEvent, &event, MAXLONG, nil ) )
  556.         {
  557.             if ( ( event.what == keyDown ) || ( event.what == autoKey ) )
  558.                 horiz = !horiz;
  559. /*            theChar = event.message & charCodeMask;
  560.             if ( theChar == 'm' )
  561.                 horiz = !horiz;
  562. */        }
  563.         
  564.         tempPoint.v = thePoint.v / kPixelSize;
  565.         tempPoint.h = thePoint.h / kPixelSize;
  566.         
  567.         /* This is really long.  If someone can shorten it, I would appreciate it. */
  568.         if (         ( !PtInRect ( thePoint, &tempRect ) ) &&
  569.                     ( Inbounds ( &tempPoint, horiz, theMin, theMax ) ) && 
  570.                     ( ItFits ( horiz, tempPoint, theMin, theMax ) ) && 
  571.                     ( ( oldPoint.h != tempPoint.h ) || ( oldPoint.v != tempPoint.v ) ) || 
  572.                     ( ( oldHoriz != horiz ) &&
  573.                     ( Inbounds ( &tempPoint, horiz, theMin, theMax ) ) &&
  574.                     ( ItFits ( horiz, tempPoint, theMin, theMax ) ) ) )
  575.         {
  576.             EraseShipPart ( oldRect );
  577.             
  578.             if ( oldHoriz )
  579.                 DrawHorizDots ( oldPoint, tempPoint, &theRect, theMin, theMax );
  580.             else
  581.                 DrawVertDots ( oldPoint, tempPoint, &theRect, theMin, theMax );
  582.             
  583.             PtToShipRect ( tempPoint, &tempRect, horiz, theMin, theMax );
  584.             if ( horiz )
  585.                 DrawShipPart ( theHorizID, tempRect );
  586.             else
  587.                 DrawShipPart ( theHorizID + 1, tempRect );
  588.     
  589.             PtToShipRect ( tempPoint, &oldRect, horiz, theMin, theMax );
  590.             PtToRect ( tempPoint, &tempRect );
  591.             oldPoint = tempPoint;
  592.             oldHoriz = horiz;
  593.         }
  594.         else if ( horiz != oldHoriz )
  595.             horiz = oldHoriz;
  596.     }
  597.     
  598.     SetShipToGrid ( you, oldPoint, horiz, theMin, theMax, theShip );
  599.     
  600.     while ( Button () );
  601. }
  602.  
  603. /**********/
  604. /* ItFits */
  605. /**********/
  606.  
  607. Boolean    ItFits ( Boolean horiz, Point thePoint, int theMin, int theMax )
  608. {
  609.     Boolean fits = FALSE;
  610.     
  611.     if  ( horiz )
  612.         fits = FitsHoriz ( you, thePoint.h - theMin, thePoint.v, 1 + theMin + theMax );
  613.     else
  614.         fits = FitsVert ( you, thePoint.h, thePoint.v - theMin, 1 + theMin + theMax );
  615.         
  616.     return ( fits );
  617. }
  618.  
  619. /*****************/
  620. /* DrawHorizDots */
  621. /*****************/
  622.  
  623. void    DrawHorizDots ( Point aPoint, Point tempPoint, Rect *theRect, int min, int max )
  624. {
  625.     int            i = aPoint.h;
  626.     int            test = i + max;
  627.     PicHandle    picture;
  628.     
  629.     picture = GetPicture ( kNullDotID );
  630.     if ( picture == nil )
  631.     {
  632.         SysBeep ( 10 );
  633.         ExitToShell ();
  634.     }
  635.     
  636.     for ( aPoint.h = i - min; aPoint.h <= test; aPoint.h++ ) 
  637.     {
  638.         /* PtToDotRect ( aPoint, theRect ); */
  639.         (*theRect).left = ( aPoint.h + 1 ) * 19 - 10;
  640.         (*theRect).top = ( aPoint.v + 1 ) * 19 - 10;
  641.         (*theRect).right = ( aPoint.h + 1 ) * 19;
  642.         (*theRect).bottom = ( aPoint.v + 1 ) * 19;
  643.         
  644.         DrawPicture ( picture, theRect );
  645.     }
  646.     
  647. }
  648.  
  649. /****************/
  650. /* DrawVertDots */
  651. /****************/
  652.  
  653. void    DrawVertDots ( Point aPoint, Point tempPoint, Rect *theRect, int min, int max )
  654. {
  655.     int         i = aPoint.v;
  656.     int            test = i + max;
  657.     PicHandle    picture;
  658.     
  659.     picture = GetPicture ( kNullDotID );
  660.     if ( picture == nil )
  661.     {
  662.         SysBeep ( 10 );
  663.         ExitToShell ();
  664.     }
  665.     
  666.     for ( aPoint.v = i - min; aPoint.v <= test; aPoint.v++ )
  667.     {
  668.         /* PtToDotRect ( aPoint, theRect ); */
  669.         (*theRect).left = ( aPoint.h + 1 ) * 19 - 10;
  670.         (*theRect).top = ( aPoint.v + 1 ) * 19 - 10;
  671.         (*theRect).right = ( aPoint.h + 1 ) * 19;
  672.         (*theRect).bottom = ( aPoint.v + 1 ) * 19;
  673.         
  674.         DrawPicture ( picture, theRect );
  675.     }
  676.     
  677. }
  678.  
  679. /***************/
  680. /* PtToDotRect */
  681. /***************/
  682.  
  683. void    PtToDotRect ( Point aPoint, Rect *aRect )
  684. {
  685.     (*aRect).left = ( aPoint.h + 1 ) * 19 - 10;
  686.     (*aRect).top = ( aPoint.v + 1 ) * 19 - 10;
  687.     (*aRect).right = ( aPoint.h + 1 ) * 19;
  688.     (*aRect).bottom = ( aPoint.v + 1 ) * 19;
  689. }
  690.  
  691. /************/
  692. /* PtToRect */
  693. /************/
  694.  
  695. void    PtToRect ( Point aPoint, Rect *aRect )
  696. {
  697.     (*aRect).left = ( aPoint.h + 1 ) * 19 - 16;
  698.     (*aRect).top = ( aPoint.v + 1 ) * 19 - 16;
  699.     (*aRect).right = ( aPoint.h + 1 ) * 19 + 6;
  700.     (*aRect).bottom = ( aPoint.v + 1 ) * 19 + 6;
  701. }
  702.  
  703. /****************/
  704. /* PtToShipRect */
  705. /****************/
  706.  
  707. void    PtToShipRect ( Point aPoint, Rect *aRect, Boolean horiz, int min, int max )
  708. {
  709.     if ( horiz )
  710.     {
  711.         (*aRect).left = ( aPoint.h + 1 ) * 19 - 10 - ( kPixelSize * min );
  712.         (*aRect).top = ( aPoint.v + 1 ) * 19 - 10;
  713.         (*aRect).right = ( aPoint.h + 1 ) * 19 + ( kPixelSize * max );
  714.         (*aRect).bottom = ( aPoint.v + 1 ) * 19;
  715.     }
  716.     else
  717.     {
  718.         (*aRect).left = ( aPoint.h + 1 ) * 19 - 10;
  719.         (*aRect).top = ( aPoint.v + 1 ) * 19 - 10 - ( kPixelSize * min );
  720.         (*aRect).right = ( aPoint.h + 1 ) * 19;
  721.         (*aRect).bottom = ( aPoint.v + 1 ) * 19 + ( kPixelSize * max );
  722.     }
  723. }
  724.  
  725. /*****************/
  726. /* SetShipToGrid */
  727. /*****************/
  728. /* purpose: This function takes the current location of the ship upon a mouse down
  729. /*             and puts it into the grid.
  730. /* variables: The grid to set it to; the point of the current mouse location
  731. /*            after it has been translated to the grid coordinates; the vertical
  732. /*            or horizontal orientation of the ship; the minimum grid point that the
  733. /*            ship is at; the maximum grid point that the ship is at; the character
  734. /*            type of the ship.
  735.  */
  736.  
  737. void    SetShipToGrid ( Grid theGrid[][kGridSize], Point tempPoint, 
  738.                             Boolean horiz, int min, int max, int c )
  739. {
  740.     int i;
  741.     
  742.     if ( horiz )
  743.     {
  744.         if ( ( c == kCarrier ) || ( c == kSinkShip ) ||
  745.                 ( c == kDestroyer ) || ( c == kCruiser ) )
  746.             theGrid[tempPoint.h - min][tempPoint.v].shipResID = 133;
  747.         else
  748.             theGrid[tempPoint.h - min][tempPoint.v].shipResID = 134;
  749.         
  750.         theGrid[tempPoint.h - min][tempPoint.v].shipType = c;
  751.         
  752.         for ( i = tempPoint.h - ( min - 1 ); i <= tempPoint.h + ( max - 1 ); i++ )
  753.         {
  754.             theGrid[i][tempPoint.v].shipResID = 135;
  755.             theGrid[i][tempPoint.v].shipType = c;
  756.         }
  757.         
  758.         if ( ( c == kSub ) || ( c == kCruiser ) || ( c == kDestroyer ) )
  759.             theGrid[tempPoint.h + max][tempPoint.v].shipResID = 136;
  760.         else
  761.             theGrid[tempPoint.h + max][tempPoint.v].shipResID = 137;
  762.  
  763.         theGrid[tempPoint.h + max][tempPoint.v].shipType = c;
  764.     }
  765.     else
  766.     {
  767.         if ( ( c == kCarrier ) || ( c == kSinkShip ) ||
  768.                 ( c == kDestroyer ) || ( c == kCruiser ) )
  769.             theGrid[tempPoint.h][tempPoint.v - min].shipResID = 138;
  770.         else
  771.             theGrid[tempPoint.h][tempPoint.v - min].shipResID = 139;
  772.         
  773.         theGrid[tempPoint.h][tempPoint.v - min].shipType = c;
  774.         
  775.         for ( i = tempPoint.v - ( min - 1 ); i <= tempPoint.v + ( max - 1 ); i++ )
  776.         {
  777.             theGrid[tempPoint.h][i].shipResID = 140;
  778.             (theGrid[tempPoint.h][i].shipType) = c;
  779.         }
  780.         
  781.         if ( ( c == kSub ) || ( c == kCruiser ) || ( c == kDestroyer ) )
  782.             theGrid[tempPoint.h][tempPoint.v + max].shipResID = 141;
  783.         else
  784.             theGrid[tempPoint.h][tempPoint.v + max].shipResID = 142;
  785.         
  786.         (theGrid[tempPoint.h][tempPoint.v + max].shipType) = c;
  787.     }
  788. }
  789.  
  790. /************/
  791. /* DrawDots */
  792. /************/
  793.  
  794. void    DrawDots ( Grid theGrid[][kGridSize] )
  795. {
  796.     Rect        pictureRect;
  797.     WindowPtr    window;
  798.     PicHandle    hitDot, missDot, nullDot;
  799.     int            i, j, windowSize;
  800.     Boolean        isYou = FALSE;
  801.     
  802.     if ( theGrid == you )
  803.         isYou = TRUE;
  804.     
  805.     window = FrontWindow ();
  806.     windowSize = window->portRect.right - window->portRect.left;
  807.  
  808.     EraseRect ( &window->portRect );
  809.     
  810.     if ( useColor )
  811.     {
  812.         hitDot = GetPicture ( kHitDotID );
  813.         if ( hitDot == nil )
  814.         {
  815.             SysBeep ( 10 );
  816.             ExitToShell ();
  817.         }
  818.     }
  819.     else
  820.     {
  821.         hitDot = GetPicture ( kBWHitDotID );
  822.         if ( hitDot == nil )
  823.         {
  824.             SysBeep ( 10 );
  825.             ExitToShell ();
  826.         }
  827.     }
  828.  
  829.     missDot = GetPicture ( kMissDotID );
  830.     if ( missDot == nil )
  831.     {
  832.         SysBeep ( 10 );
  833.         ExitToShell ();
  834.     }
  835.  
  836.     nullDot = GetPicture ( kNullDotID );
  837.     if ( nullDot == nil )
  838.     {
  839.         SysBeep ( 10 );
  840.         ExitToShell ();
  841.     }
  842.     
  843.     i = 0;
  844.     for ( i; i <= 9; i++ )
  845.     {
  846.         j = 0;
  847.         for ( j; j <= 9; j++ )
  848.         {
  849.             pictureRect.left = ( i + 1 ) * 19 - 10;
  850.             pictureRect.top = ( j + 1 ) * 19 - 10;
  851.             pictureRect.right = ( i + 1 ) * 19;
  852.             pictureRect.bottom = ( j + 1 ) * 19;
  853.             
  854.             if ( isYou && ( theGrid[i][j].shipResID != 0 ) )
  855.                 DrawShipPart ( theGrid[i][j].shipResID, pictureRect );
  856.             else if ( ( ( enemyCount >= 17 ) || ( youCount >= 17 ) ) &&
  857.                             ( theGrid[i][j].shipResID != 0 ) )
  858.                 DrawShipPart ( theGrid[i][j].shipResID, pictureRect );
  859.             
  860.             if ( theGrid[i][j].hitOrMiss == noTry )
  861.                 DrawPicture ( nullDot, &pictureRect );
  862.             else if ( theGrid[i][j].hitOrMiss == miss )
  863.                 DrawPicture ( missDot, &pictureRect );
  864.             else
  865.                 DrawPicture ( hitDot, &pictureRect );
  866.         }
  867.     }
  868.     CheckIfSink ( kCarrier, kNoSound );
  869.     CheckIfSink ( kSinkShip, kNoSound );
  870.     CheckIfSink ( kCruiser, kNoSound );
  871.     CheckIfSink ( kSub, kNoSound );
  872.     CheckIfSink ( kDestroyer, kNoSound );
  873. }
  874.  
  875. /****************/
  876. /* DrawShipPart */
  877. /****************/
  878.  
  879. void    DrawShipPart ( int resID, Rect pictureRect )
  880. {
  881.     PicHandle    picture;
  882.  
  883.     pictureRect.left -= 3;
  884.     pictureRect.top -= 3;
  885.     pictureRect.right += 3;
  886.     pictureRect.bottom += 3;
  887.             
  888.     picture = GetPicture ( resID );
  889.     if ( picture == nil )
  890.     {
  891.         SysBeep ( 10 );
  892.         ExitToShell ();
  893.     }
  894.  
  895.     DrawPicture ( picture, &pictureRect );
  896. }
  897.  
  898. /*****************/
  899. /* EraseShipPart */
  900. /*****************/
  901.  
  902. void    EraseShipPart ( Rect pictureRect )
  903. {
  904.     pictureRect.left -= 3;
  905.     pictureRect.top -= 3;
  906.     pictureRect.right += 3;
  907.     pictureRect.bottom += 3;
  908.             
  909.     EraseRect ( &pictureRect );
  910. }
  911.  
  912. /************/
  913. /* GridInit */
  914. /************/
  915.  
  916. void    GridInit ( Grid aGrid[][kGridSize] )
  917. {
  918.     int        i, j;
  919.     
  920.     for ( i = 0; i < kGridSize; i++ )
  921.     {
  922.         for ( j = 0; j < kGridSize; j++ )
  923.         {
  924.             aGrid[i][j].shipType = kNoShip;
  925.             aGrid[i][j].shipResID = 0;
  926.             aGrid[i][j].hitOrMiss = noTry;
  927.         }
  928.     }
  929. }
  930.  
  931. /*******************/
  932. /* PlaceEnemyShips */
  933. /*******************/
  934.  
  935. void    PlaceEnemyShips ( void )
  936. {
  937.     int        s;
  938.     unsigned long myRand = qd.randSeed;
  939.     
  940.     GetDateTime( &myRand );
  941.     
  942.     GridInit ( enemy );
  943.  
  944.     PlaceAnEnemyShip ( kCarrierSize, kCarrierMin, kCarrierMax, kCarrier );
  945.     PlaceAnEnemyShip ( kSinkShipSize, kSinkShipMin, kSinkShipMax, kSinkShip );
  946.     PlaceAnEnemyShip ( kCruiserSize, kCruiserMin, kCruiserMax, kCruiser );
  947.     PlaceAnEnemyShip ( kSubSize, kSubMin, kSubMax, kSub );
  948.     PlaceAnEnemyShip ( kDestroyerSize, kDestroyerMin, kDestroyerMax, kDestroyer );
  949. }
  950.  
  951. /********************/
  952. /* PlaceAnEnemyShip */
  953. /********************/
  954.  
  955. void    PlaceAnEnemyShip ( int shipSize, int min, int max, int c )
  956. {
  957.     Boolean                ItDoesntFit = TRUE, horiz;
  958.     int                 dir;
  959.     Point                aPoint;
  960.     
  961.     while ( ItDoesntFit )
  962.     {
  963.         aPoint.h = Randomize ();
  964.         aPoint.v = Randomize ();
  965.         
  966.         dir = Randomize ();
  967.         
  968.         if ( ( ( float ) dir / 2 ) == ( dir / 2 ) )       /* It's even so horizontal */
  969.         {
  970.             if ( ( aPoint.h <= 10 - shipSize ) && ( aPoint.h >= 0 ) && 
  971.                         ( FitsHoriz ( enemy, aPoint.h, aPoint.v, shipSize ) ) )
  972.             {
  973.                 horiz = TRUE;
  974.                 aPoint.h += min;
  975.                 SetShipToGrid ( enemy, aPoint, horiz, min, max, c );
  976.                 ItDoesntFit = FALSE;
  977.             }
  978.         }
  979.         else                                            /* It's odd so vertical */
  980.         {
  981.             if ( ( aPoint.v <= 10 - shipSize ) && ( aPoint.v >= 0 ) && 
  982.                         ( FitsVert ( enemy, aPoint.h, aPoint.v, shipSize ) ) )
  983.             {
  984.                 horiz = FALSE;
  985.                 aPoint.v += min;
  986.                 SetShipToGrid ( enemy, aPoint, horiz, min, max, c );
  987.                 ItDoesntFit = FALSE;
  988.             }
  989.         }
  990.     }
  991. }
  992.  
  993. /************/
  994. /* FitsVert */
  995. /************/
  996.  
  997. Boolean    FitsVert ( Grid theGrid[][kGridSize], int x, int y, int shipSize )
  998. {
  999.     Boolean fits = TRUE;
  1000.     int        i;
  1001.     
  1002.     for ( i = y; i < y + shipSize; i++ )
  1003.     {
  1004.         if ( theGrid[x][i].shipResID != 0 )
  1005.             fits = FALSE;
  1006.     }
  1007.     return ( fits );
  1008. }
  1009.  
  1010. /*************/
  1011. /* FitsHoriz */
  1012. /*************/
  1013.  
  1014. Boolean    FitsHoriz ( Grid theGrid[][kGridSize], int x, int y, int shipSize )
  1015. {
  1016.     Boolean fits = TRUE;
  1017.     int        i;
  1018.     
  1019.     for ( i = x; i < x + shipSize; i++ )
  1020.     {
  1021.         if ( theGrid[i][y].shipResID != 0 )
  1022.             fits = FALSE;
  1023.     }
  1024.     return ( fits );
  1025. }
  1026.  
  1027. /*************/
  1028. /* Randomize */
  1029. /*************/
  1030.  
  1031. int        Randomize ( void )
  1032. {
  1033.     long    randomNumber;
  1034.     
  1035.     randomNumber = Random ();
  1036.     
  1037.     if ( randomNumber < 0 )
  1038.         randomNumber *= -1;
  1039.     
  1040.     if ( randomNumber == 0 )
  1041.         return ( randomNumber );
  1042.     else
  1043.         return ( ( ( randomNumber * kRandomRange ) / kRandomUpperLimit ) );
  1044. }
  1045.  
  1046. /**************/
  1047. /* CheckPoint */
  1048. /**************/
  1049.  
  1050. void    CheckPoint ( Point mouseLocal )
  1051. {
  1052.     Rect        dotRect;
  1053.     Point        mouseCopy;
  1054.     Handle        mySndHandle;
  1055.     
  1056.     GlobalToLocal ( &mouseLocal );
  1057.     mouseCopy = mouseLocal;
  1058.     
  1059.     if ( mouseLocal.v == 200 )
  1060.         mouseLocal.v = 9;
  1061.     else
  1062.         mouseLocal.v /= kPixelSize;
  1063.     if ( mouseLocal.h == 200 )
  1064.         mouseLocal.h = 9;
  1065.     else
  1066.         mouseLocal.h /= kPixelSize;
  1067.     
  1068.     PtToDotRect ( mouseLocal, &dotRect );
  1069.             
  1070.     if ( ( PtInRect ( mouseCopy, &dotRect ) ) &&
  1071.                  ( enemy[mouseLocal.h][mouseLocal.v].hitOrMiss == noTry ) )
  1072.     {
  1073.         if ( gHasSound )
  1074.         {
  1075.             mySndHandle = GetResource ( 'snd ', kBombDropSnd );
  1076.             if ( mySndHandle != NULL )
  1077.                 SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1078.         }
  1079.         
  1080.         if ( enemy[mouseLocal.h][mouseLocal.v].shipResID == 0 )
  1081.         {
  1082.             enemy[mouseLocal.h][mouseLocal.v].hitOrMiss = miss;
  1083.             DrawOneDot ( kMissDotID, &dotRect );
  1084.         
  1085.             if ( gHasSound )
  1086.             {
  1087.                 mySndHandle = GetResource ( 'snd ', kSplashSnd );
  1088.                 if ( mySndHandle != NULL )
  1089.                     SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1090.             }
  1091.         }
  1092.         else
  1093.         {
  1094.             enemy[mouseLocal.h][mouseLocal.v].hitOrMiss = hit;
  1095.             (hitShips[(enemy[mouseLocal.h][mouseLocal.v].shipType)])++;
  1096.             DrawOneDot ( kHitDotID, &dotRect );
  1097.             CheckIfSink ( (enemy[mouseLocal.h][mouseLocal.v].shipType), kSound );
  1098.             
  1099.             if ( gHasSound )
  1100.             {
  1101.                 mySndHandle = GetResource ( 'snd ', kExplosionSnd );
  1102.                 if ( mySndHandle != NULL  )
  1103.                     SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1104.             }
  1105.             
  1106.             enemyCount++;
  1107.         }
  1108.         
  1109.         gYouHasGone = TRUE;
  1110.     }
  1111. }
  1112.  
  1113.  
  1114. /***************/
  1115. /* CheckIfSink */
  1116. /***************/
  1117.  
  1118. int        CheckIfSink ( int theShip, Boolean play )
  1119. {
  1120.     Boolean    drawParts = FALSE;
  1121.     int        i = 0;
  1122.     int        j = 0;
  1123.     Rect    theRect;
  1124.     Handle    mySndHandle;
  1125.     
  1126.     switch ( theShip )
  1127.     {
  1128.         case kCarrier:
  1129.             if ( hitShips[theShip] == kCarrierSize )
  1130.                 drawParts = TRUE;
  1131.             break;
  1132.         case kSinkShip:
  1133.             if ( hitShips[theShip] == kSinkShipSize )
  1134.             {
  1135.                 drawParts = TRUE;
  1136.                 if ( gHasSound && play )
  1137.                 {
  1138.                     mySndHandle = GetResource ( 'snd ', kYouSankSnd );
  1139.                     if ( mySndHandle != NULL )
  1140.                         SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1141.                 }
  1142.             }
  1143.             break;
  1144.         case kCruiser:
  1145.             if ( hitShips[theShip] == kCruiserSize )
  1146.                 drawParts = TRUE;
  1147.             break;
  1148.         case kSub:
  1149.             if ( hitShips[theShip] == kSubSize )
  1150.                 drawParts = TRUE;
  1151.             break;
  1152.         case kDestroyer:
  1153.             if ( hitShips[theShip] == kDestroyerSize )
  1154.                 drawParts = TRUE;
  1155.             break;
  1156.     }
  1157.     if ( drawParts )
  1158.     {
  1159.         for ( i = 0; i < kGridSize; i++ )
  1160.         {
  1161.             for ( j = 0; j < kGridSize; j++ )
  1162.             {
  1163.                 if ( (enemy[i][j].shipType) == theShip )
  1164.                 {
  1165.                     theRect.left = ( i + 1 ) * 19 - 10;
  1166.                     theRect.top = ( j + 1 ) * 19 - 10;
  1167.                     theRect.right = ( i + 1 ) * 19;
  1168.                     theRect.bottom = ( j + 1 ) * 19;
  1169.                     
  1170.                     DrawShipPart ( enemy[i][j].shipResID,theRect );
  1171.                 }
  1172.             }
  1173.         }
  1174.     }
  1175. }
  1176.  
  1177.  
  1178. /**************/
  1179. /* DrawOneDot */
  1180. /**************/
  1181.  
  1182. void    DrawOneDot ( int dotID, Rect *dotRect )
  1183. {
  1184.     PicHandle    picture;
  1185.     
  1186.     picture = GetPicture ( dotID );
  1187.     if ( picture == nil )
  1188.     {
  1189.         SysBeep ( 10 );
  1190.         ExitToShell ();
  1191.     }
  1192.     DrawPicture ( picture, dotRect );
  1193. }
  1194.  
  1195. /************/
  1196. /* Inbounds */
  1197. /************/
  1198.  
  1199. Boolean    Inbounds ( Point *tempPoint, Boolean horiz, int min, int max )
  1200. {
  1201.     Boolean    vTest = TRUE;
  1202.     Boolean hTest = TRUE;
  1203.     
  1204.     if ( horiz )
  1205.     {
  1206.         if ( (*tempPoint).h < min )
  1207.         {
  1208.             (*tempPoint).h = min;
  1209.             hTest = FALSE;
  1210.         }
  1211.         if ( (*tempPoint).h > ( 9 - max ) )
  1212.         {
  1213.             (*tempPoint).h = ( 9 - max );
  1214.             hTest = FALSE;
  1215.         }
  1216.         if ( (*tempPoint).v < 0 )
  1217.         {
  1218.             (*tempPoint).v = 0;
  1219.             vTest = FALSE;
  1220.         }
  1221.         if ( (*tempPoint).v > 9 )
  1222.         {
  1223.             (*tempPoint).v = 9;
  1224.             vTest = FALSE;
  1225.         }
  1226.     }
  1227.     
  1228.     else
  1229.     {
  1230.         if ( (*tempPoint).v < min )
  1231.         {
  1232.             (*tempPoint).v = min;
  1233.             hTest = FALSE;
  1234.         }
  1235.         if ( (*tempPoint).v > ( 9 - max ) )
  1236.         {
  1237.             (*tempPoint).v = ( 9 - max );
  1238.             hTest = FALSE;
  1239.         }
  1240.         if ( (*tempPoint).h < 0 )
  1241.         {
  1242.             (*tempPoint).h = 0;
  1243.             vTest = FALSE;
  1244.         }
  1245.         if ( (*tempPoint).h > 9 )
  1246.         {
  1247.             (*tempPoint).h = 9;
  1248.             vTest = FALSE;
  1249.         }
  1250.     }
  1251.         
  1252.     if ( ( hTest == FALSE ) && ( vTest == FALSE ) )
  1253.         return ( FALSE );
  1254.     else
  1255.         return ( TRUE );
  1256. }
  1257.  
  1258. /*****************/
  1259. /* PickEnemyShot */
  1260. /*****************/
  1261.  
  1262. void    PickEnemyShot ( void )
  1263. {
  1264.     Rect                theRect;
  1265.     
  1266.     static cond            lastTry = miss;
  1267.     static Point        lastPoint =  {0,0}, firstHitPoint  = {0,0};
  1268.     static Boolean        keepTrying = FALSE, isHorizontal = FALSE, hitsYet = FALSE;
  1269.     static Direction    lastDir = right;
  1270.     static Point        thisPoint = {0,0};
  1271.     
  1272.     if ( !youCount )
  1273.     {
  1274.         lastTry = miss;
  1275.         keepTrying = FALSE;
  1276.         isHorizontal = FALSE;
  1277.         hitsYet = FALSE;
  1278.         lastDir = right;
  1279.     }
  1280.  
  1281.     if ( keepTrying == TRUE )
  1282.     {
  1283.         if ( ( lastDir == right ) && ( thisPoint.h < 9 ) )
  1284.         {
  1285.             thisPoint.h++;
  1286.             
  1287.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1288.             {
  1289.                 lastTry = PlaceTheShot ( thisPoint );
  1290.                 
  1291.                 if ( lastTry == miss )
  1292.                 {
  1293.                     thisPoint = firstHitPoint;
  1294.                     lastDir = left;
  1295.                 }
  1296.                 
  1297.                 if ( lastTry ==  hit )
  1298.                 {
  1299.                     lastPoint = thisPoint;
  1300.                     hitsYet = TRUE;
  1301.                     isHorizontal = TRUE;
  1302.                 }
  1303.                 return;
  1304.             }
  1305.             else
  1306.             {
  1307.                 thisPoint = firstHitPoint;
  1308.                 lastDir = left;
  1309.             }
  1310.         }
  1311.         else if ( ( lastDir == right ) && ( ( isHorizontal ) || ( thisPoint.h == 9 ) ) )
  1312.         {
  1313.             thisPoint = firstHitPoint;
  1314.             lastDir = left;
  1315.         }
  1316.         
  1317.         if ( ( lastDir == left ) && ( thisPoint.h > 0 ) )
  1318.         {
  1319.             thisPoint.h--;
  1320.             
  1321.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1322.             {
  1323.                 lastTry = PlaceTheShot ( thisPoint );
  1324.                 
  1325.                 switch ( lastTry )
  1326.                 {
  1327.                     case hit:
  1328.                         lastPoint = thisPoint;
  1329.                         isHorizontal = TRUE;
  1330.                         hitsYet = TRUE;
  1331.                         break;
  1332.  
  1333.                     case miss:
  1334.                         if ( hitsYet )
  1335.                         {
  1336.                             keepTrying = FALSE;
  1337.                             lastDir = right;
  1338.                             hitsYet = FALSE;
  1339.                         }
  1340.                         else
  1341.                         {
  1342.                             thisPoint = firstHitPoint;
  1343.                             lastDir = up;
  1344.                         }
  1345.                         break;
  1346.                 }
  1347.                     
  1348.                 return;
  1349.             }
  1350.             else
  1351.             {
  1352.                 if  ( hitsYet )
  1353.                 {
  1354.                     lastDir = right;
  1355.                     keepTrying = FALSE;
  1356.                     hitsYet = FALSE;
  1357.                 }
  1358.                 else
  1359.                 {
  1360.                     thisPoint = firstHitPoint;
  1361.                     lastDir = up;
  1362.                 }
  1363.             }
  1364.         }
  1365.         else if ( ( isHorizontal ) || ( lastDir == left ) )
  1366.         {
  1367.             if  ( hitsYet )
  1368.             {
  1369.                 lastDir = right;
  1370.                 keepTrying = FALSE;
  1371.                 hitsYet = FALSE;
  1372.             }
  1373.             else
  1374.             {
  1375.                 lastDir = up;
  1376.             }
  1377.         }
  1378.  
  1379.         if ( ( lastDir == up ) && ( thisPoint.v > 0 ) )
  1380.         {
  1381.             thisPoint.v--;
  1382.             
  1383.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1384.             {
  1385.                 lastTry = PlaceTheShot ( thisPoint );
  1386.                 
  1387.                 if ( lastTry == miss )
  1388.                 {
  1389.                     thisPoint = firstHitPoint;
  1390.                     lastDir = down;
  1391.                 }
  1392.                 
  1393.                 if ( lastTry ==  hit )
  1394.                 {
  1395.                     lastPoint = thisPoint;
  1396.                     hitsYet = TRUE;
  1397.                 }
  1398.                 return;
  1399.             }
  1400.             else
  1401.             {
  1402.                 thisPoint = firstHitPoint;
  1403.                 lastDir = down;
  1404.             }
  1405.         }
  1406.         else if ( ( !isHorizontal ) && (lastDir == up ) )
  1407.         {
  1408.             lastDir = down;
  1409.             thisPoint = firstHitPoint;
  1410.         }
  1411.         
  1412.         if ( ( lastDir == down ) && ( thisPoint.v < 9 ) )
  1413.         {
  1414.             thisPoint.v++;
  1415.             
  1416.             if ( you[thisPoint.h][thisPoint.v].hitOrMiss == noTry )
  1417.             {
  1418.                 lastTry = PlaceTheShot ( thisPoint );
  1419.                 
  1420.                 if ( lastTry == miss )
  1421.                 {
  1422.                     if ( hitsYet )
  1423.                     {
  1424.                         keepTrying = FALSE;
  1425.                         lastDir = right;
  1426.                         hitsYet = FALSE;
  1427.                     }
  1428.                     else
  1429.                     {
  1430.                         lastPoint = thisPoint;
  1431.                         lastDir = up;
  1432.                     }
  1433.                 }
  1434.                 
  1435.                 if ( lastTry == hit )
  1436.                 {
  1437.                     hitsYet = TRUE;
  1438.                 }
  1439.                     
  1440.                 return;
  1441.             }
  1442.             else
  1443.             {
  1444.                 lastDir = right;
  1445.                 hitsYet = FALSE;
  1446.             }
  1447.         }
  1448.         else if ( !isHorizontal )
  1449.         {
  1450.             lastDir = right;
  1451.             hitsYet = FALSE;
  1452.             keepTrying  = FALSE;
  1453.         }
  1454.     }
  1455.  
  1456.     do
  1457.     {
  1458.         do
  1459.         {
  1460.             thisPoint.h = Randomize ();
  1461.         } while ( ( thisPoint.h < 0 ) || ( thisPoint.h > 9 ) );
  1462.         do
  1463.         {
  1464.             thisPoint.v = Randomize ();
  1465.         } while ( ( thisPoint.v < 0 ) || ( thisPoint.v > 9 ) );
  1466.     }  while ( IsBadRandom ( thisPoint, shotCount < kMinSpacedShots ) );
  1467.     
  1468.     lastTry = PlaceTheShot ( thisPoint );
  1469.     
  1470.     if ( lastTry == hit )
  1471.     {
  1472.         firstHitPoint = thisPoint;
  1473.         keepTrying = TRUE;
  1474.     }
  1475.     else
  1476.         keepTrying = FALSE;
  1477.     
  1478.     lastDir = right;
  1479.     lastPoint = thisPoint;
  1480.     isHorizontal = FALSE;
  1481.     
  1482.     return;
  1483. }
  1484.  
  1485. /***************/
  1486. /* IsBadRandom */
  1487. /***************/
  1488.  
  1489. Boolean    IsBadRandom ( Point thePoint, Boolean canCheck )
  1490. {
  1491.     Point    tempPoint = thePoint;
  1492.     
  1493.     if ( ( you[thePoint.h][thePoint.v].hitOrMiss == hit ) ||
  1494.                 ( you[thePoint.h][thePoint.v].hitOrMiss == miss ) )
  1495.         return ( TRUE );
  1496.     
  1497.     if ( canCheck ) /* After a certain number of tries which is #define, 
  1498.                         this will be false.  It prevents having random
  1499.                         guesses next to each other early in the game. */
  1500.     {
  1501.         if ( thePoint.h > 0 )
  1502.         {
  1503.             if ( ( you[thePoint.h - 1][thePoint.v].hitOrMiss == hit ) ||
  1504.                         ( you[thePoint.h - 1][thePoint.v].hitOrMiss == miss ) )
  1505.                 return ( TRUE );
  1506.         }
  1507.         if ( thePoint.h < 9 )
  1508.         {
  1509.             if ( ( you[thePoint.h + 1][thePoint.v].hitOrMiss == hit ) ||
  1510.                         ( you[thePoint.h + 1][thePoint.v].hitOrMiss == miss ) )
  1511.                 return ( TRUE );
  1512.         }
  1513.         if ( thePoint.v > 0 )
  1514.         {
  1515.             if ( ( you[thePoint.h][thePoint.v-1].hitOrMiss == hit ) ||
  1516.                         ( you[thePoint.h][thePoint.v-1].hitOrMiss == miss ) )
  1517.                 return ( TRUE );
  1518.         }
  1519.         if ( thePoint.v < 9 )
  1520.         {
  1521.             if ( ( you[thePoint.h][thePoint.v+1].hitOrMiss == hit ) ||
  1522.                         ( you[thePoint.h][thePoint.v+1].hitOrMiss == miss ) )
  1523.                 return ( TRUE );
  1524.         }
  1525.     }
  1526.     
  1527.     /* If the point is surrounded by white on all sides, why guess there? */
  1528.     if ( ( you[thePoint.h - 1][thePoint.v].hitOrMiss == miss ) && 
  1529.             ( you[thePoint.h + 1][thePoint.v].hitOrMiss == miss ) &&
  1530.             ( you[thePoint.h][thePoint.v - 1].hitOrMiss == miss ) &&
  1531.             ( you[thePoint.h][thePoint.v + 1].hitOrMiss == miss ) )
  1532.         return ( TRUE );
  1533.     
  1534.     return ( FALSE );
  1535. }
  1536.  
  1537. /****************/
  1538. /* PlaceTheShot */
  1539. /****************/
  1540.  
  1541. cond    PlaceTheShot ( Point thePoint )
  1542. {
  1543.     Rect  theRect;
  1544.     Handle        mySndHandle;
  1545.     
  1546.     SetPort ( youWindow );
  1547.     
  1548.     if ( gHasSound )
  1549.     {
  1550.         mySndHandle = GetResource ( 'snd ', kBombDropSnd );
  1551.         if ( mySndHandle != NULL )
  1552.             SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1553.     }
  1554.     
  1555.     if ( you[thePoint.h][thePoint.v].shipResID != 0 )
  1556.     {
  1557.         you[thePoint.h][thePoint.v].hitOrMiss = hit;
  1558.         
  1559.         if ( gHasSound )
  1560.         {
  1561.             mySndHandle = GetResource ( 'snd ', kExplosionSnd );
  1562.             if ( mySndHandle != NULL )
  1563.                 SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1564.         }
  1565.         
  1566.         youCount++;
  1567.     }
  1568.     else
  1569.     {
  1570.         you[thePoint.h][thePoint.v].hitOrMiss = miss;
  1571.         
  1572.         if ( gHasSound )
  1573.         {
  1574.             mySndHandle = GetResource ( 'snd ', kSplashSnd );
  1575.             if ( mySndHandle != NULL )
  1576.                 SndPlay ( nil, (SndListHandle)mySndHandle, TRUE );
  1577.         }
  1578.     }
  1579.     
  1580.     PtToDotRect ( thePoint, &theRect );
  1581.     DrawOneDot ( you[thePoint.h][thePoint.v].hitOrMiss, &theRect );
  1582.     
  1583.     shotCount++;
  1584.     
  1585.     return ( you[thePoint.h][thePoint.v].hitOrMiss );
  1586. }
  1587.  
  1588. /************/
  1589. /* IsColour */
  1590. /************/
  1591.  
  1592. Boolean    IsColour( void )
  1593. {
  1594.     SysEnvRec        mySE;
  1595.     
  1596.     /* Check to see if colour quickdraw is installed */
  1597.     SysEnvirons( 2, &mySE );
  1598.     return( mySE.hasColorQD );
  1599. }
  1600.  
  1601.  
  1602.